package com.jboltai.util.http;


import com.jboltai.config.JBoltAIConfig;
import com.jboltai.event.Event;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.sse.EventSource;
import okhttp3.sse.EventSources;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

/**
 * 请求工具类，通常情况下使用Request.me即可，无需重复实例化。
 */
public class HttpUtil {


    private static final OkHttpClient client;

    /**
     * 静态初始化块，用于初始化OkHttpClient实例
     * 从JBoltAIConfig获取读取和写入超时时间，并设置到OkHttpClient
     * 设置每个域名允许的最大并发请求数和客户端的最大并发请求数
     */
    static {

        client = new OkHttpClient.Builder().readTimeout(
                        JBoltAIConfig.getHttpReadTimeout(), TimeUnit.MILLISECONDS
                ).writeTimeout(JBoltAIConfig.getHttpWriteTimeout(), TimeUnit.MILLISECONDS)
                .build();
        //异步请求每个域名允许发起的并发请求数
        client.dispatcher().setMaxRequestsPerHost(JBoltAIConfig.getMaxAsyncRequestPerHost());
        client.dispatcher().setMaxRequests(JBoltAIConfig.getMaxAsyncRequestPerClient());
    }


    /**
     * EventSource.Factory的映射，用于创建SSE连接
     */
    private static ConcurrentHashMap<OkHttpClient, EventSource.Factory> clientSSEFactoryMap = new ConcurrentHashMap<>();

    /**
     * 获取或创建EventSource.Factory
     *
     * @param client OkHttpClient实例
     * @return EventSource.Factory实例
     */
    static EventSource.Factory getSSEFactory(OkHttpClient client) {
        return clientSSEFactoryMap.computeIfAbsent(client, EventSources::createFactory);
    }


    /**
     * 发送POST请求
     *
     * @param url 请求的URL
     * @return RequestInstance实例
     */
    public static RequestInstance post(String url) {
        return new RequestInstance(client, url, HttpMethod.POST);
    }

    /**
     * 使用指定的OkHttpClient发送POST请求
     *
     * @param client OkHttpClient实例
     * @param url    请求的URL
     * @return RequestInstance实例
     */
    public static RequestInstance post(OkHttpClient client, String url) {

        return new RequestInstance(client, url, HttpMethod.POST);
    }


    /**
     * 使用指定的OkHttpClient发送POST请求
     *
     * @param client OkHttpClient实例
     * @param url    请求的URL
     * @param event 触发请求的事件
     * @return RequestInstance实例
     */
    public static RequestInstance post(OkHttpClient client, String url, Event event) {

        return new RequestInstance(client, url, HttpMethod.POST, event);
    }

    /**
     * 发送GET请求
     *
     * @param url 请求的URL
     * @return RequestInstance实例
     */
    public static RequestInstance get(String url) {
        return new RequestInstance(client, url, HttpMethod.GET);
    }

    /**
     * 使用指定的OkHttpClient发送GET请求
     *
     * @param client OkHttpClient实例
     * @param url    请求的URL
     * @return RequestInstance实例
     */
    public static RequestInstance get(OkHttpClient client, String url) {

        return new RequestInstance(client, url, HttpMethod.GET);
    }

    public static EventSource newEventSource(OkHttpClient client, Request request, Consumer<String> successHandler, BiConsumer<Response, Throwable> failHandler) {
        return HttpUtil.getSSEFactory(client).newEventSource(request, new SSEListener(successHandler, failHandler));
    }
}
